﻿/// <reference name="MicrosoftAjax.js"/>
Type.registerNamespace("AccessKeyHighlighterControl");

AccessKeyHighlighterControl.AccessKeyHighlighter = function AccessKeyHighlighter$AccessKeyHighlighter() {
    AccessKeyHighlighterControl.AccessKeyHighlighter.initializeBase(this);
    // Privates
    this._highlightCssClass = "";
    this._popupCssClass = "";
    this._accessKeyTag = "";
    this._highlightMode = AccessKeyHighlighterControl.AccessKeyHighlightMode.ToggleLabelClass;
    this._labelAccessKeysHighlighted = false;
    this._keyDownHandler = null;
    this._keyUpHandler = null;
    this._accessKeyPopups = [];
    this._accessKeyPopupFields = [];
    this._popupLabelOffsetX = 0;
    this._popupLabelOffsetY = 0;
    this._popupButtonOffsetX = 0;
    this._popupButtonOffsetY = 0;
    this._requiresShiftAlt = window.navigator.userAgent.indexOf("Firefox") > 0;
    this._requiresHighlighting = window.navigator.userAgent.indexOf("Opera") < 0;
}

AccessKeyHighlighterControl.AccessKeyHighlighter.prototype = {
    initialize: function() {
        AccessKeyHighlighterControl.AccessKeyHighlighter.callBaseMethod(this, 'initialize');

        // Create delegates and add handlers
        if (this._requiresHighlighting) {
            this._keyDownHandler = Function.createDelegate(this, this._keyDown);
            $addHandler(document, "keydown", this._keyDownHandler);

            this._keyUpHandler = Function.createDelegate(this, this._keyUp);
            $addHandler(document, "keyup", this._keyUpHandler);

            // Create the access key popups
            this.createPopups();
        }
    },
    dispose: function() {
        // Clean-up popups
        this.clearPopups();

        // Release handlers
        if (this._requiresHighlighting) {
            $removeHandler(document, 'keydown', this._keyDownHandler);
            this._keyDownHandler = null;

            $removeHandler(document, 'keyup', this._keyUpHandler);
            this._keyUpHandler = null;
        }

        AccessKeyHighlighterControl.AccessKeyHighlighter.callBaseMethod(this, 'dispose');
    },

    // << Properties >>
    get_highlightCssClass: function() {
        /// <summary>The CSS clas to highlight access keys in labels with</summary>
        return this._highlightCssClass;
    },
    set_highlightCssClass: function(value) {
        this._highlightCssClass = value;
    },

    get_popupCssClass: function() {
        /// <summary>The CSS class to apply to access key popups</summary>
        return this._popupCssClass;
    },
    set_popupCssClass: function(value) {
        this._popupCssClass = value;
    },

    get_highlightMode: function() {
        /// <summary>The mode to highlight access keys with: ToggleLabelClass or DisplayPopup</summary>
        return this._highlightMode;
    },
    set_highlightMode: function(value) {
        this._highlightMode = value;
    },

    get_accessKeyTag: function() {
        /// <summary>The tag used to mark-up access keys in labels</summary>
        return this._accessKeyTag;
    },
    set_accessKeyTag: function(value) {
        this._accessKeyTag = value;
    },

    get_popupLabelOffsetX: function() {
        /// <summary>The x offset to use when displaying access key popups</summary>
        return this._popupLabelOffsetX;
    },
    set_popupLabelOffsetX: function(value) {
        this._popupLabelOffsetX = value;
    },

    get_popupLabelOffsetY: function() {
        /// <summary>The y offset to use when displaying access key popups</summary>
        return this._popupLabelOffsetY;
    },
    set_popupLabelOffsetY: function(value) {
        this._popupLabelOffsetY = value;
    },

    get_popupButtonOffsetX: function() {
        /// <summary>The x offset to use when displaying access key popups</summary>
        return this._popupButtonOffsetX;
    },
    set_popupButtonOffsetX: function(value) {
        this._popupButtonOffsetX = value;
    },

    get_popupButtonOffsetY: function() {
        /// <summary>The y offset to use when displaying access key popups</summary>
        return this._popupButtonOffsetY;
    },
    set_popupButtonOffsetY: function(value) {
        this._popupButtonOffsetY = value;
    },

    // << Public Methods >>
    createPopups: function() {
        /// <summary>Creates popups for access keys on the form</summary>
        if (this._highlightMode == AccessKeyHighlighterControl.AccessKeyHighlightMode.DisplayPopup) {
            this._accessKeyPopups = [];
            this._accessKeyPopupFields = [];

            // Create popups for labels
            var els = document.getElementsByTagName(this._accessKeyTag);
            var el = null;
            for (var i = 0; i < els.length; i++) {
                el = els[i];
                var innerText = (el.firstChild != null && el.firstChild.nodeType == 3 ? el.firstChild.nodeValue : "");
                var formField = el.parentNode.tagName.toUpperCase() == "LABEL" ? $get(el.parentNode.htmlFor) : null;
                if (formField != null && (
                       (typeof (formField.accessKey) != "undefined" && formField.accessKey.toUpperCase() == innerText.toUpperCase()) ||
                       (typeof (el.parentNode.accessKey) != "undefined" && el.parentNode.accessKey.toUpperCase() == innerText.toUpperCase())
                                          )) {
                    var label = el.parentNode;
                    var accessKey = (formField.accessKey != "" ? formField.accessKey : label.accessKey);
                    this._createPopup(label, accessKey);
                }
            }
            els = null;

            // Create popups for buttons
            var btns = document.getElementsByTagName("button");
            var btn = null;
            for (var i = 0; i < btns.length; i++) {
                btn = btns[i];
                if (typeof (btn.accessKey) != "undefined" && btn.accessKey != "") {
                    this._createPopup(btn, btn.accessKey);
                }
            }
            btns = null;

            // Create popups for intputs where type is submit, button or image
            var inputs = document.getElementsByTagName("input");
            var input = null;
            for (var i = 0; i < inputs.length; i++) {
                input = inputs[i];
                if ((input.type == "submit" || input.type == "button" || input.type == "image") &&
                        typeof (input.accessKey) != "undefined" && input.accessKey != "") {
                    this._createPopup(input, input.accessKey);
                }
            }
            inputs = null;
        }
    },

    clearPopups: function() {
        /// <summary>Clears all access key popups from the form</summary>
        for (var i = this._accessKeyPopups.length - 1; i >= 0; i--) {
            document.body.removeChild(this._accessKeyPopups[i]);
            this._accessKeyPopups.pop();
            this._accessKeyPopupFields.pop();
        }
        this._accessKeyPopups = [];
        this._accessKeyPopupFields = [];
    },

    refreshPopups: function() {
        /// <summary>Clears and the re-creates access key popups for the form</summary>
        this.clearPopups();
        this.createPopups();
    },

    // << Element Event Handlers >>
    _keyDown: function(sender) {
        Sys.Debug.trace(String.format("AccessKeyHighlighter document.keyDown: keyCode={0}, altKey={1}, shiftKey={2}", sender.keyCode, sender.altKey, sender.shiftKey));
        if (!this._labelAccessKeysHighlighted && (
                (sender.keyCode == 18 && !this._requiresShiftAlt) ||
                (sender.keyCode == 16 && sender.altKey && this._requiresShiftAlt) ||
                (sender.keyCode == 18 && sender.shiftKey && this._requiresShiftAlt))) {
            // Highlight all the access keys
            this._highlightAccessKeys(true);
            this._labelAccessKeysHighlighted = true;
        }
    },

    _keyUp: function(sender) {
        Sys.Debug.trace(String.format("AccessKeyHighlighter document.keyUp: keyCode={0}, altKey={1}, shiftKey={2}", sender.keyCode, sender.altKey, sender.shiftKey));
        if (this._labelAccessKeysHighlighted) {
            // Un-highlight all the access keys
            this._highlightAccessKeys(false);
            this._labelAccessKeysHighlighted = false;
        }
    },

    // << Private Methods >>
    _createPopup: function(field, accessKey) {
        /// <summary>Creates an access key popup and adds it to the global array</summary>
        /// <param name="field" isDomElement="true"></param>
        /// <param name="accessKey" type="String"></param>
        /// <returns isDomElement="true"></returns>
        var popupLocation = Sys.UI.DomElement.getLocation(field);
        popupLocation.x = popupLocation.x + (field.tagName.toUpperCase() == "LABEL" ? this._popupLabelOffsetX : this._popupButtonOffsetX);
        popupLocation.y = popupLocation.y + (field.tagName.toUpperCase() == "LABEL" ? this._popupLabelOffsetY : this._popupButtonOffsetY);

        // Create popup element, set its location and classs and add to the global array
        var popup = document.createElement("div");
        popup.appendChild(document.createTextNode(accessKey));
        Sys.UI.DomElement.setLocation(popup, popupLocation.x, popupLocation.y);
        Sys.UI.DomElement.addCssClass(popup, this._popupCssClass);
        document.body.appendChild(popup);
        this._accessKeyPopups.push(popup);
        this._accessKeyPopupFields.push(field);
        return popup;
    },

    _highlightAccessKeys: function(highlight) {
        /// <summary>Toggles the highlighting of access keys on the page</summary>
        /// <param name="highlight" type="Boolean"></param
        if (this._highlightMode == AccessKeyHighlighterControl.AccessKeyHighlightMode.DisplayPopup) {
            // Popups
            for (var i = 0; i < this._accessKeyPopups.length; i++) {
                // Update the popup's location
                var field = this._accessKeyPopupFields[i];
                var popupLocation = Sys.UI.DomElement.getLocation(field);
                popupLocation.x = popupLocation.x + (field.tagName.toUpperCase() == "LABEL" ? this._popupLabelOffsetX : this._popupButtonOffsetX);
                popupLocation.y = popupLocation.y + (field.tagName.toUpperCase() == "LABEL" ? this._popupLabelOffsetY : this._popupButtonOffsetY);
                Sys.UI.DomElement.setLocation(this._accessKeyPopups[i], popupLocation.x, popupLocation.y);
                this._accessKeyPopups[i].style.display = highlight ? "block" : "none";
            }
        }
        else {
            // Toggle label class
            var els = document.getElementsByTagName(this._accessKeyTag);
            var el = null;
            for (var i = 0; i < els.length; i++) {
                el = els[i];
                var innerText = (el.firstChild != null && el.firstChild.nodeType == 3 ? el.firstChild.nodeValue : "");
                var formField = el.parentNode.tagName.toUpperCase() == "LABEL" ? $get(el.parentNode.htmlFor) : null;
                if (formField != null && (formField.accessKey.toUpperCase() == innerText.toUpperCase()
                                      || el.parentNode.accessKey.toUpperCase() == innerText.toUpperCase())) {
                    var label = el.parentNode;
                    // Set CSS class
                    if (highlight) {
                        Sys.UI.DomElement.addCssClass(el, this._highlightCssClass);
                    }
                    else {
                        Sys.UI.DomElement.removeCssClass(el, this._highlightCssClass);
                    }
                }
            }
        }
    }
}

AccessKeyHighlighterControl.AccessKeyHighlighter.registerClass('AccessKeyHighlighterControl.AccessKeyHighlighter', Sys.Component);

AccessKeyHighlighterControl.AccessKeyHighlightMode = function(){};
AccessKeyHighlighterControl.AccessKeyHighlightMode.prototype = 
{
    ToggleLabelClass:   0,
    DisplayPopup:       1
}
AccessKeyHighlighterControl.AccessKeyHighlightMode.registerEnum("AccessKeyHighlighterControl.AccessKeyHighlightMode");


if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();